/************************************
 文件明 ：  bsp_key_filter.h
 作者   ：  胡秋峰
 描述   ：  按键驱动头文件(定时器+中断消抖)
 ************************************/
#include "bsp_key_filter.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"

/* 静态函数声明 */
static void filter_timer_irq_handler(void);
static void gpio1_16_31_irq_handler(void);

/**
 * @描述    ： 按键初始化
 * @参数    ： 无
 * @返回值  ： 无
 */
void filter_key_init()
{
    gpio_pin_config_t key_config;

    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0XF080);

    key_config.direction = kGPIO_DigitalInput;
    key_config.outputLogic = 1;
    key_config.mode = kGPIO_IntFallingEdge;
    gpio_init(GPIO1, 18, &key_config);

    GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
    system_register_irq_handler(GPIO1_Combined_16_31_IRQn,
                                (system_irq_handler_t)gpio1_16_31_irq_handler,
                                NULL);
    gpio_int_enable(GPIO1, 18);
    filter_timer_init(66000000/100);
}

/**
 * @描述    ： 初始化用于按键消抖的定时器，默认关闭定时器
 * @参数    ： 无
 * @返回值  ： 无
 */
void filter_timer_init(uint32_t value)
{
    EPIT1->CR = 0;

    /**
     * CR寄存器：
     * [25:24]  01      时钟源选择Peripheral clock = 66MHZ
     * [15:4]   0       分频值
     * [3]      1       当计数器到0的话，从LR寄存器重新加载数值
     * [2]      1       比较中断使能
     * [1]      1       初始计数值来源于LR寄存器
     * [0]      0       先关闭EPIT1
     */ 
    EPIT1->CR = (0x1 << 24) |
                (0 << 4) |
                (1 << 3) | 
                (1 << 2) | 
                (1 << 1) | 
                (0 << 0);
    EPIT1->LR = value; /* 加载寄存器 */
    EPIT1->CMPR = 0; /* 比较寄存器 */

    GIC_EnableIRQ(EPIT1_IRQn);
    system_register_irq_handler(EPIT1_IRQn, 
                                (system_irq_handler_t)filter_timer_irq_handler,
                                NULL);
}

/**
 * @描述    ： 关闭定时器
 * @参数    ： 无
 * @返回值  ： 无
 */
void filter_timer_stop(void)
{
    EPIT1->CR &= ~(1<<0);
}

/**
 * @描述    ： 重启定时器
 * @参数    ： 无
 * @返回值  ： 无
 */
void filter_timer_restart(uint32_t value)
{
    EPIT1->CR &= ~(1 << 0);
    EPIT1->LR = value;
    EPIT1->CR |= (1 << 0);
}

/**
 * @描述    ： 定时器中断处理函数
 * @参数    ： 无
 * @返回值  ： 无
 */
void filter_timer_irq_handler(void)
{
    static uint8_t state = 0;
    
    if (EPIT1->SR & (1 << 0)) {
        filter_timer_stop();
        if (gpio_pin_read(GPIO1, 18) == 0) {
            state = !state;
            beep_switch(state);
        }
    }
    EPIT1->SR |= (1 << 0);
}

/**
 * @描述    ： 外部中断处理函数
 * @参数    ： 无
 * @返回值  ： 无
 */
static void gpio1_16_31_irq_handler(void)
{
    filter_timer_restart(66000000/100);
    gpio_clear_int_flags(GPIO1, 18);
}